#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "scanner.h"

#include <QBuffer>
#include <QFileDialog>
#include <QMessageBox>
#include <QProcess>
#include <QScrollBar>
#include <QTimer>
#include <windows.h>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , op()
{
    ui->setupUi(this);

    setWindowTitle("词法分析过程");
    resize(this->width() + 260, this->height());
    ShowAuto(":/Auto/auto0.png");
    ui->textEdit_showAuto->setReadOnly(true);

    // 导入源代码
    connect(ui->pushButton_getCode, &QPushButton::clicked, this, [=]() {
        // 弹出文件选择对话框
        QString filePath = QFileDialog::getOpenFileName(
            this, tr("选择文件"), ":/", tr("文本文件 (*.txt)"));

        // 检查用户是否选择了文件
        if (!filePath.isEmpty()) {
            ShowCode(filePath.toUtf8());
        }
    });

    Scanner into;
    QVector<Character> listChar;
    QVector<Word> listKeyword;
    into.ScanChar(listChar);
    into.ScanWord(listKeyword, _keyword);

    // 按钮禁用
    ui->pushButton_outputWord->setEnabled(false);

    // 词法分析
    connect(ui->pushButton_startAuto, &QPushButton::clicked, this, [=]() {
        list.clear();
        ui->tableWidget_showToken->clearContents();

        auto str = GetCode();
        int ptr = 0, lineCount = 1;
        int countRow = 0;
        while (ptr < str.size()) {
            Character c1 = Automation::TestChar(listChar, str[ptr].toLatin1());
            if (c1.GetVariety() == _not_match) {
                auto c2 = c1.GetContent();
                if (c2 != '\n' && c2 != '\r') {
                    QMessageBox::critical(nullptr, "错误",
                                          QString("字符%1未找到").arg(c1.GetContent()));
                    break;
                }
            }
            auto w1 = Automation::Tell(str, ptr, lineCount);

            if (w1[0].second.GetVariety() == _identifier) {
                auto tok = Automation::Lookup(listKeyword, w1[0]);

                SetToken(tok, countRow);
                list.push_back(tok);

            } else if (w1.size() > 1) {
                if (w1.size() < 3) {
                    QMessageBox::critical(nullptr, "错误",
                                          QString("未找到字符与第%1行%2匹配")
                                              .arg(w1[0].first)
                                              .arg(w1[0].second.GetContent()));
                } else {
                    foreach (const auto &var, w1) {

                        SetToken(var, countRow);
                        list.push_back(var);

                    }
                }
            } else {

                SetToken(w1[0], countRow);
                list.push_back(w1[0]);

            }
        }
        // 回滚到最开头一行
        ui->tableWidget_showToken->scrollToTop();

        QMessageBox::information(nullptr, "提示", "分析完成");

        ui->pushButton_outputWord->setEnabled(true);
    });

    // 导出单词
    connect(ui->pushButton_outputWord, &QPushButton::clicked, this, [=]() {
        QString fileName = QFileDialog::getOpenFileName(
            this, tr("选择文件"), ":/", tr("文本文件 (*.txt)"));
        // 检查用户是否选择了文件
        if (!fileName.isEmpty()) {
            auto path = op.write(list, fileName.toUtf8());
            if(path != "") {
                QMessageBox::information(nullptr,"保存成功","当前文件保存在" + path);
            }
        }
    });

    // 查看字符表
    connect(ui->menu_Char, &Menu::DoubleClick, this, [=]() {
        this->close();
        emit LookChar();
    });
    // 查看关键字表
    connect(ui->menu_Keyword, &Menu::DoubleClick, this, [=]() {
        this->close();
        emit LookKeyword();
    });
    // 查看单字符分隔符表
    connect(ui->menu_Single, &Menu::DoubleClick, this, [=]() {
        this->close();
        emit LookSingle();
    });
    // 查看单词种类
    connect(ui->menu_Variety, &Menu::DoubleClick, this, [=]() {
        this->close();
        emit LookVariety();
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

QString MainWindow::GetCode() {
    return ui->textEdit_showCode->toPlainText();
}

void MainWindow::ShowCode(QByteArray filePath) {
    Scanner into;
    auto str = into.ScanFile(filePath);

    ui->textEdit_showCode->setFontPointSize(qreal(14));
    ui->textEdit_showCode->setText(str);
}

void MainWindow::SetToken(const Token& tok, int& row) {
    auto tmp = tok.second.GetContent();
    if(tmp == " " || tmp == "\n" || tmp == "\r") {
        return ;
    }
    if(row > ui->tableWidget_showToken->rowCount()) {
        row = ui->tableWidget_showToken->rowCount();
    }
    // auto row = ui->tableWidget_showToken->rowCount();
    if(row >= ui->tableWidget_showToken->rowCount()) {
        ui->tableWidget_showToken->insertRow(row);
    }

    ui->tableWidget_showToken->setItem(row,0,new QTableWidgetItem(QString::number(tok.first)));
    ui->tableWidget_showToken->setItem(row,1,new QTableWidgetItem(tok.second.GetContent()));
    if(tok.second.GetVariety() == _unknown) {
        ui->tableWidget_showToken->setItem(row++,2,new QTableWidgetItem("注释内容或字符串"));
        return ;
    }
    ui->tableWidget_showToken->setItem(row++,2,new QTableWidgetItem(tok.second.GetVarietyString_cn()));
}

void MainWindow::ShowAuto(QByteArray filePath) {
    ui->textEdit_showAuto->clear();

    QTextImageFormat imageFormat;
    imageFormat.setName(filePath);
    imageFormat.setWidth(3.3 * ui->textEdit_showAuto->width());
    imageFormat.setHeight(16 * ui->textEdit_showAuto->height());

    QTextCursor cursor = ui->textEdit_showAuto->textCursor();
    cursor.movePosition(QTextCursor::Start);

    cursor.insertImage(imageFormat);
}
